package net.yienyien.process.bpel.generator.partner;

import java.util.HashMap;
import java.util.Map;

import javax.xml.namespace.QName;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil;
import org.eclipse.wst.wsdl.Input;
import org.eclipse.wst.wsdl.Operation;
import org.eclipse.wst.wsdl.Output;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.WSDLFactory;

import net.yienyien.process.bpd.BPDModel;
import net.yienyien.process.bpel.generator.Production;
import net.yienyien.process.folder.BPDFoldListener;
import net.yienyien.process.folder.artifacts.BPDPattern;
import net.yienyien.process.folder.artifacts.PatternedBPDComponent;
import net.yienyien.process.pmm.Binding;
import net.yienyien.process.pmm.Bindings;
import net.yienyien.process.pmm.PartnerBinding;
import net.yienyien.process.pmm.PmmFactory;

public class CompositePmmManager implements BPDFoldListener {

	public static final String NAME="net.yienyien.process.bpel.generator.controlFlow.PmmAdder";
	private Bindings pmm;
	private Map<EClass, Integer> count;
	private PortType componentsPT;
	private Production prod;
	
	public CompositePmmManager(Production prod, Bindings pmm) {
		this.pmm=pmm;
		this.prod=prod;
		count=new HashMap<EClass, Integer>();
	}
	
	public String freshName(BPDPattern pattern) {
		Integer n=count.get(pattern.eClass());
		if(n==null) {
			count.put(pattern.eClass(), 0);
			n=0;
		} else {
			count.put(pattern.eClass(), n+1);
			n++;
		}
		
		return pattern.getName()+"_"+n;
	}
	
	private PortType getPortType() {
		if(componentsPT==null) {
			componentsPT=WSDLFactory.eINSTANCE.createPortType();
			QName ptQName=(QName) XMLTypeUtil.createQName(prod.getProcessWSDL().getTargetNamespace(), "ComponentsPortType", "");
			componentsPT.setQName(ptQName);
			prod.getProcessWSDL().addPortType(componentsPT);
		}
		
		return componentsPT;
	}
	
	@Override
	public void fold(BPDModel model, PatternedBPDComponent pcomp) {
		Operation compositeOp=WSDLFactory.eINSTANCE.createOperation();
		String name=freshName(pcomp.getPattern());
		
		Input input=WSDLFactory.eINSTANCE.createInput();
		Output output=WSDLFactory.eINSTANCE.createOutput();
		compositeOp.setName(name);
		compositeOp.setInput(input);
		compositeOp.setOutput(output);
		
		getPortType().getOperations().add(compositeOp);
		
		PartnerBinding binding=PmmFactory.eINSTANCE.createPartnerBinding();
		binding.setOperation(compositeOp);
		binding.setRole(name+"Role");
		binding.setTask(pcomp);
		
		pmm.getBindings().add(binding);
	}

	@Override
	public String getName() {
		return NAME;
	}

	@Override
	public void post(BPDModel model) {
	}

	@Override
	public void pre(BPDModel model) {
	}

}
